// $codepro.audit.disable variableShouldBeFinal, useEquals
/*
 * Records package
 */
/*
 * 
 */
/*
 * 
 */

/*
 * 
 */




/* */

/* Records package
 * 
 */

/*
 * 
 */
package edu.gatech.oad.records;
import edu.gatech.oad.ui.UserPanel;
import edu.gatech.oad.user.Patient;
import edu.gatech.oad.user.Receptionist;
import edu.gatech.oad.user.User;

import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.BoxLayout;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.border.TitledBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 * Implementation of a JPanel to display the Patients medical history
 * @author Nathan Hurley
 * @version 1.0
 */
public class PatientHistoryPanel extends JPanel {
	/**
	 * Serializable variable
	 */
	private static final long serialVersionUID = 1L;
	
	/**
	 * The PatientHistory to be displayed
	 */
	private PatientHistory curHistory;
	
	/**
	 * Buttons to remove and open TreatmentRecords and LabResults
	 * save is used to update the medicalProfile when appropriate user
	 * changes it
	 */
	private JButton remove, open, save;
	
	/**
	 * The current User of the JPanel
	 */
	private User curUser;
	
	/**
	 * Lists representing the TreatmentRecords and LabResults in
	 * the PatientHistory
	 */
	private JList treatRecs, labRes;
	
	/**
	 * ListModels for the treatRecs and LabRes
	 */
	private DefaultListModel treatModel, labModel;
	
	/**
	 * holds the TreatmentRecords list
	 * holds the LabResults list
	 * holds treatRecords and labRecords
	 * holds the buttons
	 * holds the patients information
	 */
	private JPanel treatRecords, records, labRecords, buttonsPanel, patientInfo;
	
	/**
	 * Tabbed pane to add lab results and treatment records
	 */
	private final UserPanel pan;
	
	/**
	 * TextArea used to edit the medicalProfle. Only available to
	 * appropriate Users
	 */
	private JTextArea staffMedProfile;
	
	/**
	 * Listener to determine if the one JLists selection needs to be removed
	 */
	private SelectionListener changeList;
	
	/**
	 * Listener for the open, save, and remove buttons
	 */
	private final ButtonListener buttonListen;
	
	/**
	 * ScrollPane for the staffMedProfile
	 */
	private JScrollPane curPane;
	
	/**
	 * Width of the panel
	 */
	private static final int PANEL_WIDTH = 750;
	
	/**
	 * Height of the panel
	 */
	private static final int PANEL_HEIGHT = 500;
	
	/**
	 * First part of substring for Date
	 */
	private static final int DATE_START = 10;
	
	/**
	 * Start of end substring for Date
	 */
	private static final int DATE_END_START = 23;
	
	/**
	 * End of final substring for the Date
	 */
	private static final int DATE_END = 28;
	
	/**
	 * Number of rows in textareas and layout
	 */
	private static final int ROWS = 2;
	
	/**
	 * Creates a panel to represent a Patients medical history
	 * @param curHistory the PatientHistory to build panel around
	 * @param user the user viewing the panel
	 * @param pan UserPanel to add to
	 */
	public PatientHistoryPanel(PatientHistory curHistory, User user, UserPanel pan){ // $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.effectivejava.constructorsOnlyInvokeFinalMethods
		/*Take in parameters*/
		this.pan = pan;
		this.curUser = user;
		this.curHistory = curHistory;
		/*Set Layout and size*/
		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		/*Create listeners*/
		changeList = new SelectionListener();
		buttonListen = new ButtonListener();
		/*Prepare inner panels*/
		preparePatientInfoPanel();
		prepareTreatRecordsPanel();
		prepareLabRecordsPanel();
		prepareRecordsPanel();
		prepareButtonsPanel();
		/*Add panels*/
		add(patientInfo);
		add(records);
		add(buttonsPanel);
		changeAccess();//changes panel if user is a Patient
		setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
	}
	
	/**
	 * Changes the panel if the user is a patient
	 */
	public void changeAccess(){
		if(curUser instanceof Patient || curUser instanceof Receptionist){
			buttonsPanel.remove(save);//removes ability to save from user
			buttonsPanel.remove(remove);//removes ability to remove records
			staffMedProfile.setEditable(false);
		}
	}
	
	/**
	 * Creates the recordsPanel to hold the treatRecords and labRecords panels
	 */
	public void prepareRecordsPanel(){
		records = new JPanel();
		records.setLayout(new GridLayout(1, ROWS));
		records.add(treatRecords);
		records.add(labRecords);
	}
	
	/**
	 * Creates the patientInfo panel containing the medicalProfile
	 */
	public void preparePatientInfoPanel(){
		patientInfo = new JPanel();
		
		patientInfo.setLayout(new BoxLayout(patientInfo, BoxLayout.Y_AXIS));
		patientInfo.setBorder(new TitledBorder(curHistory.getPatient() + 
				" Medical History"));
		patientInfo.setAlignmentX(RIGHT_ALIGNMENT);
		staffMedProfile = new JTextArea(curHistory.getMedicalProfile());
		staffMedProfile.getDocument().addDocumentListener(new TextChangedListener());
		staffMedProfile.setRows(ROWS);
		staffMedProfile.setLineWrap(true);
		staffMedProfile.setWrapStyleWord(true);
		curPane = new JScrollPane(staffMedProfile);
		patientInfo.add(curPane);
	}
	
	/**
	 * Creates the treatRecords panel to hold the JList containing the
	 * list of TreatmentRecords
	 */
	public void prepareTreatRecordsPanel(){
		treatRecords = new JPanel();
		treatRecords.setBorder(new TitledBorder("Treatment Records"));
		treatRecords.setLayout(new BoxLayout(treatRecords, BoxLayout.Y_AXIS));
		treatModel = new DefaultListModel();
		treatRecs = new JList(treatModel);
		for(TreatmentRecord t: curHistory.getTreatmentRecords()){
			treatModel.addElement(t);
		}
		treatRecs.addMouseListener(new ListClickListener());
		treatRecs.addListSelectionListener(changeList);
		treatRecords.add(new JScrollPane(treatRecs));
		
	}
	
	/**
	 * Creates the labRecordsPanel containing the JList of the LabResults
	 */
	public void prepareLabRecordsPanel(){
		labRecords = new JPanel();
		labRecords.setBorder(new TitledBorder("Lab Results"));
		labRecords.setLayout(new BoxLayout(labRecords, BoxLayout.Y_AXIS));
		labModel = new DefaultListModel();
		labRes = new JList(labModel);
		for(LabResults l: curHistory.getLabResults()){
			labModel.addElement(l);
		}
		labRes.addMouseListener(new ListClickListener());
		labRes.addListSelectionListener(changeList);
		labRecords.add(new JScrollPane(labRes));
	}
	
	/**
	 * Updates the panel when the tab is clicked by readding
	 * the LabResults and TreatmentRecords
	 */
	public void updatePanel(){
		labModel.clear();
		for(LabResults l: curHistory.getLabResults()){
			labModel.addElement(l);
		}
		treatModel.clear();
		for(TreatmentRecord t: curHistory.getTreatmentRecords()){
			treatModel.addElement(t);
		}
	}
	
	/**
	 * Creates the buttonsPanel to hold the open, save, and remove buttons
	 */
	public void prepareButtonsPanel(){
		buttonsPanel = new JPanel();
		remove = new JButton("Remove");
		open = new JButton("Open");
		//open.setAlignmentX(RIGHT_ALIGNMENT);
		save = new JButton("Save");
		remove.addActionListener(buttonListen);
		open.addActionListener(buttonListen);
		save.addActionListener(buttonListen);
		buttonsPanel.add(remove);
		buttonsPanel.add(save);
		buttonsPanel.add(open);
	}
	
	/**
	 * ActionListener for the open, save, and remove buttons
	 * @author Nathan Hurley
	 */
	private class ButtonListener implements ActionListener{
		/**
		 * Controller to remove records from the PatientHistory
		 */
		private PatientHistoryController historyControl = 
			new PatientHistoryController(curHistory);
		
		/**
		 * Performs an action based on which button has been clicked
		 * @param e the event that has occurred
		 */
		public void actionPerformed(ActionEvent e){
			if(e.getSource() == remove){
				if(treatRecs.getSelectedIndex() != -1){
					int result = JOptionPane.showConfirmDialog(
						    treatRecords,
						    "Are you sure you want to delete the treatment record from " 
						    + treatRecs.getSelectedValue() + "?\n Deleting this record " +
				    		"will delete any Lab Results and Prescriptions " +
				    		"that were created during this treatment!",
						    "Confirm Removal of Record",
						    JOptionPane.YES_NO_OPTION);
					if(result == JOptionPane.YES_OPTION){
						historyControl.removeTreatRec((TreatmentRecord) 
								treatRecs.getSelectedValue(), labModel);
						treatModel.removeElement(treatRecs.getSelectedValue()); // $codepro.audit.disable com.instantiations.assist.eclipse.analysis.unusedReturnValue
					}
				}
				else if(labRes.getSelectedIndex() != -1){
					int result = JOptionPane.showConfirmDialog(treatRecords, 
							"Are you sure you want to delete the Lab Result named " 
							+ labRes.getSelectedValue() + "?\n Deleting this result" +
							"will delete the Lab Order associated with it!",
						    "Confirm Removal of Lab Record",
						    JOptionPane.YES_NO_OPTION);
					if(result == JOptionPane.YES_OPTION){
						historyControl.removeLab((LabResults) labRes.getSelectedValue());
						labModel.removeElement(labRes.getSelectedValue()); // $codepro.audit.disable com.instantiations.assist.eclipse.analysis.unusedReturnValue
					}
				}
			}
			else if(e.getSource() == open){
				if(treatRecs.getSelectedIndex() != -1){
					TreatmentRecord newRecord = (TreatmentRecord) 
						treatRecs.getSelectedValue();
	        		String date = newRecord.getDate().toString();
	        		String newDate = date.substring(0, DATE_START) + 
	        		date.substring(DATE_END_START, DATE_END);
	        		pan.addNewTab(newDate, new TreatmentRecordPanel((TreatmentRecord)
	        				treatRecs.getSelectedValue(), curUser, pan));
				}
				else{
					if(labRes.getSelectedIndex() != -1){
		        		pan.addNewTab(((LabResults) 
		        				labRes.getSelectedValue()).toString(), 
		        				new LabResultsPanel((LabResults) 
		        						labRes.getSelectedValue(), curUser));
					}
				}
				
			}
			else if(e.getSource() == save){
				curHistory.setMedicalProfile(staffMedProfile.getText());
			}
		}
		
		/**
		 * @return location of this listener
		 */
		public String toString(){
			return "Button Listener for the PatientHistoryPanel";
		}
	}
	
	/**
	 * Listener for clicks on the JLists to change to new panel
	 * @author Nathan Hurley
	 *
	 */
	private class ListClickListener extends MouseAdapter{
		/**
		 * Represents a double click by the user
		 */
		private static final int MAX_CLICKS = 2;
		
		/**
		 * Changes panels when user double clicks an element in one of the
		 * JLists
		 * @param evt the mouse event that has occurred
		 */
		public void mouseClicked(MouseEvent evt) {
	        final JList list = (JList) evt.getSource();
	        if(list.equals(treatRecs)){
	        	if (evt.getClickCount() == MAX_CLICKS) {
	        		final int index = list.locationToIndex(evt.getPoint());
	        		if(index != -1){
	        			final TreatmentRecord newRecord = 
	        				(TreatmentRecord) treatModel.get(index);
	        			final String date = newRecord.getDate().toString();
	        			final String newDate = date.substring(0, DATE_START) 
	        			+ date.substring(DATE_END_START, DATE_END);
	        			if(!treatModel.isEmpty()){
	        				pan.addNewTab(newDate, 
	        						new TreatmentRecordPanel(newRecord, curUser, pan));
	        			}
	        		}
	        	}
	        }
	        else if(list.equals(labRes)){
	        	if (evt.getClickCount() == MAX_CLICKS) {
	        		final int index = list.locationToIndex(evt.getPoint());
	        			if(index != -1){
	        			if(!labModel.isEmpty()){
	        				pan.addNewTab(((LabResults) 
	        						labRes.getSelectedValue()).toString(), 
	        						new LabResultsPanel((LabResults) 
	        								labModel.get(index), curUser));
	        			}
	        		}
        		} 
	        }
	    }
		
		/**
		 * @return location of this mouse listener
		 */
		public String toString(){
			return "Mouse Listener for PatientHistoryPanel";
		}
	}
	
	/**
	 * Listener to make sure only one JList has an element selected
	 * @author Nathan Hurley
	 */
	private class SelectionListener implements ListSelectionListener{
		/**
		 * Flag used since listener is called when clearSelection is called
		 */
		private boolean isChanging = false;
		
		/**
		 * Removes selection of 1 JList if it is selected
		 * @param e the list event that has occurred
		 */
		public void valueChanged(ListSelectionEvent e){
			if(!isChanging){
				isChanging = true;
				if(e.getSource() == treatRecs){
					labRes.clearSelection();
				}
				else if(e.getSource() == labRes){ // $codepro.audit.disable useEquals
					treatRecs.clearSelection();
				}
				isChanging = false;
			}
		}
		
		/**
		 * @return location of the listener
		 */
		public String toString(){
			return "List listener for the PatientHistoryPanel";
		}
	}
	
	/**
	 * Listens for changes in the JTextArea staffMedProfile
	 * and saves the changes
	 * @author Nathan
	 *
	 */
	private class TextChangedListener implements DocumentListener{
		/**
		 * Empty method for action not taken
		 * @param e the event that has occurred
		 */
		public void changedUpdate(DocumentEvent e){ // $codepro.audit.disable emptyMethod
		}
		
		/**
		 * Saves the JTextArea when data is removed
		 * @param e the event that has occurred
		 */
		public void removeUpdate(DocumentEvent e){
			curHistory.setMedicalProfile(staffMedProfile.getText());
		}
		
		/**
		 * Saves the JTextArea when data is added
		 * @param e the event that has occurred
		 */
		public void insertUpdate(DocumentEvent e){
			curHistory.setMedicalProfile(staffMedProfile.getText());
		}
		
		/**
		 * @return location of this listener
		 */
		public String toString(){
			return "Text changed listener for the PatientHistoryPanel";
		}
	}
	
	/**
	 * @return the PatientHistory associated with
	 * this panel
	 */
	public PatientHistory getHistory(){
		return curHistory;
	}
	
	/**
	 * Determines if an Object is equal to a PatientHistoryPanel
	 * by using the PatientHistory that the panel is built around
	 * @param o the Object to compare to
	 * @return true if equal and false otherwise
	 */
	public boolean equals(Object o){
		if(this == o){
			return true;
		}
		if(o instanceof PatientHistoryPanel){
			final PatientHistoryPanel curPanel = (PatientHistoryPanel) o;
			if(curPanel.getHistory().equals(this.getHistory())){
				return true;
			}
		}
		return false;
	}
	
	/**
	 * @return hash code for the PatientHistory associated
	 * with this panel
	 */
	public int hashCode(){
		return curHistory.hashCode();
	}
}
